home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / tools / gcc / gcc270_src.lha / gcc-2.7.0-amiga / config / winnt / ld.c next >
Encoding:
C/C++ Source or Header  |  1995-06-15  |  6.5 KB  |  291 lines

  1. /* Call Windows NT 3.x linker.
  2.    Copyright (C) 1994, 1995 Free Software Foundation, Inc.
  3.    Contributed by Douglas B. Rupp (drupp@cs.washington.edu).
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 59 Temple Place - Suite 330,
  20. Boston, MA 02111-1307, USA.  */
  21.  
  22. #include "config.h"
  23. #include <stdio.h>
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <process.h>
  29.  
  30. /* These can be set by command line arguments */
  31. char *linker_path = 0;
  32. int verbose = 0;
  33. int subsystem = 0;
  34. int entry = 0;
  35.  
  36. int link_arg_max = -1;
  37. char **link_args = (char **) 0;
  38. int link_arg_index = -1;
  39.  
  40. char *search_dirs = ".";
  41.  
  42. static int is_regular_file (char *name);
  43.  
  44. /* Add the argument contained in STR to the list of arguments to pass to the
  45.    linker */
  46.  
  47. static void
  48. addarg (str)
  49.      char *str;
  50. {
  51.   int i;
  52.  
  53.   if (++link_arg_index >= link_arg_max)
  54.     {
  55.       char **new_link_args
  56.     = (char **) calloc (link_arg_max + 1000, sizeof (char *));
  57.  
  58.       for (i = 0; i <= link_arg_max; i++)
  59.     new_link_args [i] = link_args [i];
  60.  
  61.       if (link_args)
  62.     free (link_args);
  63.  
  64.       link_arg_max += 1000;
  65.       link_args = new_link_args;
  66.     }
  67.  
  68.   link_args [link_arg_index] = str;
  69. }
  70.  
  71. /* Locate the file named in FILE_NAME in the set of paths contained in
  72.    PATH_VAL */
  73.  
  74. static char *
  75. locate_file (file_name, path_val)
  76.      char *file_name;
  77.      char *path_val;
  78. {
  79.   char buf [1000];
  80.   int file_len = strlen (file_name);
  81.   char *end_path = path_val + strlen (path_val);
  82.   char *ptr;
  83.  
  84.   /* Handle absolute pathnames */
  85.   if (file_name [0] == '/' || file_name [0] == DIR_SEPARATOR
  86.       || isalpha (file_name [0]) && file_name [1] == ':')
  87.     {
  88.       strncpy (buf, file_name, sizeof buf);
  89.       buf[sizeof buf - 1] = '\0';
  90.       if (is_regular_file (buf))
  91.     return strdup (buf);
  92.       else
  93.     return 0;
  94.   }
  95.  
  96.   if (! path_val)
  97.     return 0;
  98.  
  99.   for (;;)
  100.     {
  101.       for (; *path_val == PATH_SEPARATOR ; path_val++)
  102.     ;
  103.       if (! *path_val)
  104.     return 0;
  105.  
  106.       for (ptr = buf; *path_val && *path_val != PATH_SEPARATOR; )
  107.     *ptr++ = *path_val++;
  108.  
  109.       ptr--;
  110.       if (*ptr != '/' && *ptr != DIR_SEPARATOR)
  111.     *++ptr = DIR_SEPARATOR;
  112.  
  113.       strcpy (++ptr, file_name);
  114.  
  115.       if (is_regular_file (buf))
  116.     return strdup (buf);
  117.     }
  118.  
  119.   return 0;
  120. }
  121.  
  122. /* Given a library name in NAME, i.e. foo.  Look first for libfoo.a and then
  123.    foo.lib in the set of directories we are allowed to search in */
  124.  
  125. static char *
  126. expand_lib (name)
  127.      char *name;
  128. {
  129.   char *lib, *lib_path;
  130.  
  131.   lib = malloc (strlen (name) + 6);
  132.   strcpy (lib, "lib");
  133.   strcat (lib, name);
  134.   strcat (lib, ".a");
  135.   lib_path = locate_file (lib, search_dirs);
  136.   if (!lib_path)
  137.     {
  138.       strcpy (lib, name);
  139.       strcat (lib, ".lib");
  140.       lib_path = locate_file (lib, search_dirs);
  141.       if (!lib_path)
  142.         {
  143.           fprintf (stderr, 
  144.                    "Couldn't locate library: lib%s.a or %s.lib\n", name, name);
  145.           exit (1);
  146.         }
  147.     }
  148.  
  149.   return lib_path;
  150. }
  151.  
  152. /* Check to see if the file named in NAME is a regular file, i.e. not a
  153.    directory */
  154.  
  155. static int
  156. is_regular_file (name)
  157.      char *name;
  158. {
  159.   int ret;
  160.   struct stat statbuf;
  161.  
  162.   ret = stat(name, &statbuf);
  163.   return !ret && S_ISREG (statbuf.st_mode);
  164. }
  165.  
  166. /* Process the number of args in P_ARGC and contained in ARGV.  Look for
  167.    special flags, etc. that must be handled for the Microsoft linker */
  168.  
  169. static void
  170. process_args (p_argc, argv)
  171.      int *p_argc;
  172.      char *argv[];
  173. {
  174.   int i, j;
  175.  
  176.   for (i = 1; i < *p_argc; i++)
  177.     {
  178.       /* -v turns on verbose option here and is passed on to gcc */
  179.       if (! strcmp (argv [i], "-v"))
  180.     verbose = 1;
  181.       else if (! strncmp (argv [i], "-subsystem", 10))
  182.     subsystem = 1;
  183.       else if (! strncmp (argv [i], "-entry", 6))
  184.     entry = 1;
  185.     }
  186. }
  187.  
  188. /* The main program.  Spawn the Microsoft linker after fixing up the
  189.    Unix-like flags and args to be what the Microsoft linker wants */
  190.  
  191. main (argc, argv)
  192.      int argc;
  193.      char *argv[];
  194. {
  195.   int i;
  196.   int done_an_ali = 0;
  197.   int file_name_index;
  198.   char *pathval = getenv ("PATH");
  199.   char *spawn_args [5];
  200.   char *tmppathval = malloc (strlen (pathval) + 3);
  201.  
  202.   strcpy (tmppathval, ".;");
  203.   pathval = strcat (tmppathval, pathval);
  204.  
  205.   process_args (&argc , argv);
  206.  
  207.   linker_path = locate_file ("link32.exe", pathval);
  208.   if (!linker_path)
  209.     {
  210.       linker_path = locate_file ("link.exe", pathval);
  211.       if (!linker_path)
  212.     {
  213.       fprintf (stderr, "Couldn't locate link32 or link\n");
  214.       exit (1);
  215.     }
  216.     }
  217.  
  218.   addarg (linker_path);
  219.   if (! subsystem) addarg ("-subsystem:console");
  220.   if (! entry) addarg ("-entry:mainCRTStartup");
  221.  
  222.   for (i = 1; i < argc; i++)
  223.     {
  224.       int arg_len = strlen (argv [i]);
  225.  
  226.       if (!strcmp (argv [i], "-o"))
  227.     {
  228.       char *buff, *ptr;
  229.       int out_len;
  230.  
  231.       i++;
  232.       out_len = strlen (argv[i]) + 10;
  233.       buff = malloc (out_len);
  234.       strcpy (buff, "-out:");
  235.       strcat (buff, argv[i]);
  236.       ptr = strstr (buff, ".exe");
  237.       if (ptr == NULL || strlen (ptr) != 4)
  238.         strcat (buff, ".exe");
  239.       addarg (buff);
  240.     }
  241.       else if (arg_len > 2 && !strncmp (argv [i], "-L", 2))
  242.     {
  243.       char *nbuff, *sdbuff;
  244.       int j, new_len, search_dirs_len;
  245.  
  246.       new_len = strlen (&argv[i][2]);
  247.       search_dirs_len = strlen (search_dirs);
  248.  
  249.       nbuff = malloc (new_len + 1);
  250.       strcpy (nbuff, &argv[i][2]);
  251.  
  252.       for (j = 0; j < new_len; j++)
  253.         if (nbuff[j] == '/') nbuff[j] = DIR_SEPARATOR;
  254.  
  255.       sdbuff = malloc (search_dirs_len + new_len + 2);
  256.       strcpy (sdbuff, search_dirs);
  257.       sdbuff[search_dirs_len] = PATH_SEPARATOR;
  258.       sdbuff[search_dirs_len+1] = 0;
  259.       strcat (sdbuff, nbuff);
  260.  
  261.       search_dirs = sdbuff;
  262.     }
  263.  
  264.       else if (arg_len > 2 && !strncmp (argv [i], "-l", 2))
  265.     addarg (expand_lib (&argv[i][2]));
  266.     else if (!strcmp (argv [i], "-v")) 
  267.       ;
  268.     else
  269.       addarg (argv [i]);
  270.     }
  271.  
  272.   addarg (NULL);
  273.  
  274.   if (verbose)
  275.     {
  276.       int i;
  277.  
  278.       for (i = 0; i < link_arg_index; i++)
  279.     printf ("%s ", link_args [i]);
  280.       putchar ('\n');
  281.     }
  282.  
  283.   if (spawnvp (P_WAIT, linker_path, (const char * const *)link_args) != 0)
  284.     {
  285.       fprintf (stderr, "Error executing %s\n", link_args[0]);
  286.       exit (1);
  287.     }
  288.  
  289.   exit (0);
  290. }
  291.